package com.qlslylq.ad.sdk.core.loader;

import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import com.bytedance.sdk.openadsdk.AdSlot;
import com.bytedance.sdk.openadsdk.TTAdDislike;
import com.bytedance.sdk.openadsdk.TTAdLoadType;
import com.bytedance.sdk.openadsdk.TTAdNative;
import com.bytedance.sdk.openadsdk.TTNativeExpressAd;
import com.mbridge.msdk.out.BannerSize;
import com.mbridge.msdk.out.MBBannerView;
import com.mbridge.msdk.out.MBridgeIds;
import com.qlslylq.ad.sdk.config.CsjMgrHolder;
import com.qlslylq.ad.sdk.constant.AppConst;
import com.qlslylq.ad.sdk.core.ad.BaseAd;
import com.qlslylq.ad.sdk.core.listener.BannerAdListener;
import com.qlslylq.ad.sdk.core.mgr.PoolMgr;
import com.qlslylq.ad.sdk.core.rsp.AdError;
import com.qlslylq.ad.sdk.enums.AdEventSign;
import com.qlslylq.ad.sdk.enums.AdPlatformEnum;
import com.qlslylq.ad.sdk.enums.AdSize;
import com.qlslylq.ad.sdk.enums.ErrorEnum;
import com.qlslylq.ad.sdk.enums.OrientationEnum;
import com.qlslylq.ad.sdk.model.req.UserBehaviorAddDTO;
import com.qlslylq.ad.sdk.model.rsp.AdPlaceWebConfigureVO;
import com.qlslylq.ad.sdk.net.api.ApiServiceImpl;
import com.qlslylq.ad.sdk.util.DeviceUtil;
import com.qlslylq.ad.sdk.util.GsonUtils;
import com.qlslylq.ad.sdk.util.Log;
import com.qq.e.ads.banner2.UnifiedBannerADListener;
import com.qq.e.ads.banner2.UnifiedBannerView;

import java.util.List;

/**
 * 横幅广告加载器<br/>
 */
public class BannerAdLoader extends AdLoader<BannerAdListener> {

    //广告容器
    private ViewGroup adContainer;

    //广告容器宽度
    private int adContainerWidth;

    //广告模板尺寸
    private AdSize adSize;

    //轮播间隔时间(ms),值域：[30 * 1000，120 *1000]
    private int slideIntervalTime;

    //是否允许显示关闭按钮
    private boolean allowShowCloseBtn;

    private TTNativeExpressAd bannerViewCsj;
    private UnifiedBannerView bannerViewYlh;
    private MBBannerView bannerViewMB;

    public BannerAdLoader(Activity context, long posId, ViewGroup adContainer, BannerAdListener adListener) {
        this(context, posId, adContainer, DeviceUtil.getScreenWidth(context), null, adListener);
    }

    public BannerAdLoader(Activity context, long posId, ViewGroup adContainer, int adContainerWidth, AdSize adSize, BannerAdListener adListener) {
        super(context, posId, adListener);
        if (adContainer == null) {
            throw new IllegalArgumentException("容器参数不能为null");
        }
        if (!(adContainer instanceof LinearLayout)) {
            throw new IllegalArgumentException("容器必须是LinearLayout类型");
        }
        if (adContainerWidth <= 0) {
            adContainerWidth = DeviceUtil.getScreenWidth(context);
        }
        if (orientation == OrientationEnum.LANDSCAPE) {
            adContainerWidth = (int) Math.min(adContainerWidth, AppConst.AD_BANNER_WIDTH_MAX);
        }
        this.adContainer = adContainer;
        this.adContainerWidth = adContainerWidth;
        this.adSize = adSize;
    }

    /**
     * 加载<br/>
     */
    protected void load(AdPlaceWebConfigureVO config) {
        AdPlatformEnum platform = config.getPlatform();
        String posId = config.getPositionId();

        if (platform == AdPlatformEnum.PLATFORM_CSJ) {//穿山甲
            AdSize resultSize = AdSize.process(adSize, config.getMeasureSign());
            AdSlot adSlot = new AdSlot.Builder()
                    .setCodeId(posId)
                    .setAdCount(1)
                    .setExpressViewAcceptedSize(resultSize.getWidth(), resultSize.getHeight())//dp
                    .setAdLoadType(TTAdLoadType.PRELOAD)//[实时加载，预加载]
                    .build();
            CsjMgrHolder.createAdNative(context).loadBannerExpressAd(adSlot, new TTAdNative.NativeExpressAdListener() {
                public void onNativeExpressAdLoad(List<TTNativeExpressAd> ads) {
                    try {
                        TTNativeExpressAd ad = ads.get(0);
                        ad.setSlideIntervalTime(slideIntervalTime);

                        PoolMgr.getInstance().push(ad, config);

                        getAdListener().onAdLoad();
                    } catch (Exception e) {
                        e.printStackTrace();
                        Log.e(GsonUtils.gsonString(ErrorEnum.ERR_NO_AD.rsp(platform, adType)));
                        getAdListener().onAdLoadError(ErrorEnum.ERR_NO_AD.rsp(platform, adType));
                    }

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_RETURN_SUCCESS, BannerAdLoader.super.posId));
                }

                public void onError(int code, String msg) {
                    Log.e(GsonUtils.gsonString(AdError.build(platform, adType, code, msg)));
                    getAdListener().onAdLoadError(AdError.build(platform, adType, code, msg));

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_RETURN_FAIL, BannerAdLoader.super.posId));
                }
            });
        } else if (platform == AdPlatformEnum.PLATFORM_YLH) {//优量汇
            PoolMgr.getInstance().push(new Object(), config);
        } else if (platform == AdPlatformEnum.PLATFORM_MINTEGRAL) {
            PoolMgr.getInstance().push(new Object(), config);
        }
    }

    /**
     * 展示<br/>
     */
    protected void show(BaseAd ad) {
        destroyAd();

        AdPlaceWebConfigureVO config = ad.getConfig();
        AdPlatformEnum platform = config.getPlatform();
        String posId = config.getPositionId();

        if (platform == AdPlatformEnum.PLATFORM_CSJ) {//穿山甲
            bannerViewCsj = (TTNativeExpressAd) ad.getAd();
            bannerViewCsj.setExpressInteractionListener(new TTNativeExpressAd.ExpressAdInteractionListener() {
                public void onAdShow(View view, int type) {
                    onAdShowSafety();
                }

                public void onRenderSuccess(View view, float width, float height) {
                    if (!context.isFinishing()) {
                        closeAd();
                        //优量汇的banner物料会随控件的大小自动缩放。但穿山甲的banner物料不会随控件的大小自动缩放，其物料是绘制在控件的左上角的，是做不到完全满宽父容器的，控件的宽高只能被迫自适应内容的大小。
                        //否则强行设置大小，会致使物料显示在当前容器的左上角。
                        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                        adContainer.addView(view, params);
                    }

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_EXPOSURE, BannerAdLoader.super.posId));
                }

                public void onAdClicked(View view, int type) {
                    getAdListener().onAdClick();

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_CLICK, BannerAdLoader.super.posId));
                }

                public void onRenderFail(View view, String msg, int code) {
                    Log.e(GsonUtils.gsonString(AdError.build(platform, adType, code, msg)));
                    onAdShowErrorSafety(AdError.build(platform, adType, code, msg), platform, true);
                }
            });
            bannerViewCsj.setDislikeCallback(context, new TTAdDislike.DislikeInteractionCallback() {
                public void onShow() {
                    getAdListener().onDislikeShow();
                }

                public void onSelected(int position, String value, boolean enforce) {
                    closeAd();
                    getAdListener().onDislikeSelected(value);
                }

                public void onCancel() {
                    getAdListener().onDislikeDismiss();
                }
            });
            bannerViewCsj.render();

        } else if (platform == AdPlatformEnum.PLATFORM_YLH) {//优量汇
            UnifiedBannerADListener listener = new UnifiedBannerADListener() {
                public void onADReceive() {
                    getAdListener().onAdLoad();
                    onAdShowSafety();

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_RETURN_SUCCESS, BannerAdLoader.super.posId));
                }

                public void onADExposure() {
                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_EXPOSURE, BannerAdLoader.super.posId));
                }

                public void onADLeftApplication() {

                }

                public void onADClosed() {
                    getAdListener().onAdDismiss();

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_CLOSE, BannerAdLoader.super.posId));
                }

                public void onADClicked() {
                    getAdListener().onAdClick();

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_CLICK, BannerAdLoader.super.posId));
                }

                public void onNoAD(com.qq.e.comm.util.AdError error) {
                    Log.e(GsonUtils.gsonString(AdError.build(platform, adType, error.getErrorCode(), error.getErrorMsg())));
                    onAdShowErrorSafety(AdError.build(platform, adType, error.getErrorCode(), error.getErrorMsg()), platform, true);

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_RETURN_FAIL, BannerAdLoader.super.posId));
                }
            };
            bannerViewYlh = new UnifiedBannerView(context, posId, listener);
            bannerViewYlh.setRefresh(slideIntervalTime / AppConst.TIME_RATE);
            closeAd();
            adContainer.addView(bannerViewYlh, new LinearLayout.LayoutParams((int) adContainerWidth, (int) Math.ceil(adContainerWidth / AppConst.AD_BANNER_RATIO)));
            bannerViewYlh.loadAD();
        } else if (platform == AdPlatformEnum.PLATFORM_MINTEGRAL) {
            AdSize resultSize = AdSize.process(adSize, config.getMeasureSign());
            com.mbridge.msdk.out.BannerAdListener listener = new com.mbridge.msdk.out.BannerAdListener() {
                public void onLoadFailed(MBridgeIds mBridgeIds, String msg) {
                    Log.e(GsonUtils.gsonString(AdError.build(platform, adType, ErrorEnum.ERR_LOAD_FAILD.getId(), msg)));
                    onAdShowErrorSafety(AdError.build(platform, adType, ErrorEnum.ERR_LOAD_FAILD.getId(), msg), platform, true);

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_RETURN_FAIL, BannerAdLoader.super.posId));
                }

                public void onLoadSuccessed(MBridgeIds mBridgeIds) {
                    getAdListener().onAdLoad();

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_RETURN_SUCCESS, BannerAdLoader.super.posId));
                }

                public void onLogImpression(MBridgeIds mBridgeIds) {
                    onAdShowSafety();
                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_EXPOSURE, BannerAdLoader.super.posId));
                }

                public void onClick(MBridgeIds mBridgeIds) {
                    getAdListener().onAdClick();

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_CLICK, BannerAdLoader.super.posId));
                }

                public void onLeaveApp(MBridgeIds mBridgeIds) {

                }

                public void showFullScreen(MBridgeIds mBridgeIds) {

                }

                public void closeFullScreen(MBridgeIds mBridgeIds) {

                }

                public void onCloseBanner(MBridgeIds mBridgeIds) {
                    getAdListener().onAdDismiss();

                    ApiServiceImpl.addTrack(UserBehaviorAddDTO.build(config, AdEventSign.AD_CLOSE, BannerAdLoader.super.posId));
                }
            };
            bannerViewMB = new MBBannerView(context);
            bannerViewMB.init(new BannerSize(BannerSize.DEV_SET_TYPE, resultSize.getWidth(), resultSize.getHeight()), null, posId);
            bannerViewMB.setAllowShowCloseBtn(allowShowCloseBtn);
            bannerViewMB.setRefreshTime(slideIntervalTime / AppConst.TIME_RATE);
            bannerViewMB.setBannerAdListener(listener);
            closeAd();
            adContainer.addView(bannerViewMB, new LinearLayout.LayoutParams((int) adContainerWidth, resultSize.getRealHeight(adContainerWidth)));
            bannerViewMB.load();
        }
    }

    /**
     * 设置轮播间隔时间(ms),值域：[30 * 1000，120 *1000]
     */
    public void setSlideIntervalTime(int slideIntervalTime) {
        this.slideIntervalTime = slideIntervalTime;
    }

    /**
     * 是否允许显示关闭按钮<br/>
     */
    public void setAllowShowCloseBtn(boolean allowShowCloseBtn) {
        this.allowShowCloseBtn = allowShowCloseBtn;
    }

    /**
     * 关闭广告<br/>
     */
    public void closeAd() {
        adContainer.removeAllViews();
    }

    /**
     * 销毁广告<br/>
     */
    public void destroyAd() {
        if (bannerViewCsj != null) {
            bannerViewCsj.destroy();
        }
        if (bannerViewYlh != null) {
            bannerViewYlh.destroy();
        }
        if (bannerViewMB != null) {
            bannerViewMB.release();
        }
    }

}
